package com.tangyuan.live.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tangyuan.common.config.RedissonConfig;
import com.tangyuan.common.result.Result;
import com.tangyuan.common.result.ResultCodeEnum;
import com.tangyuan.dto.GivingLiveGiftDto;
import com.tangyuan.feignapis.user.IUserBalanceFeignClient;
import com.tangyuan.feignapis.user.IUserFeignClient;
import com.tangyuan.live.entity.dto.GiveGiftDto;
import com.tangyuan.live.entity.vo.GiftRankingVo;
import com.tangyuan.live.service.LiveGiftService;
import com.tangyuan.live.service.LiveGiveGiftService;
import com.tangyuan.live.mapper.LiveGiveGiftMapper;
import com.tangyuan.live.service.LiveRoomService;
import com.tangyuan.live.util.IMUtil;
import com.tangyuan.model.User;
import com.tangyuan.model.UserBalance;
import com.tangyuan.model.live.LiveGift;
import com.tangyuan.model.live.LiveGiveGift;
import com.tangyuan.model.live.LiveRoom;
import com.tangyuan.result.oConvertUtils;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@Slf4j
public class LiveGiveGiftServiceImpl extends ServiceImpl<LiveGiveGiftMapper, LiveGiveGift>
    implements LiveGiveGiftService{

    @Autowired
    IUserFeignClient userFeignClient;
    @Autowired
    LiveRoomService liveRoomService;
    @Autowired
    LiveGiftService liveGiftService;
    @Autowired
    IUserBalanceFeignClient userBalanceFeignClient;
    @Autowired
    IMUtil imUtil;
    private final RedissonClient redissonClient = RedissonConfig.createRedissonClient();
    @Override
    public BigDecimal getLiveIncome(Long roomId) {
        return baseMapper.getLiveIncome(roomId);
    }

    @Override
    public List<GiftRankingVo> giftRanking(Long roomId) {
        List<GiftRankingVo> rankingVos = baseMapper.giftRanking(roomId);
        if(CollectionUtils.isEmpty(rankingVos)){
            return new ArrayList<>();
        }
        List<Long> longs = rankingVos.stream().map(GiftRankingVo::getUserId).collect(Collectors.toList());
        Map<Long, User> listById = userFeignClient.getUserListById(longs);
        for (GiftRankingVo rankingVo : rankingVos) {
            User user = listById.get(rankingVo.getUserId());
            if(user != null){
                rankingVo.setUserName(user.getName());
                rankingVo.setHeadImage(user.getHeadImage());
            }
        }
        return rankingVos;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<ResultCodeEnum> giveGifts(Long userId, GiveGiftDto dto) {

        RLock lock = redissonClient.getLock("giveGift:" + dto.getRoomId());
        lock.lock(10, TimeUnit.SECONDS);
        String orderNo = "";
        GivingLiveGiftDto giftDto = null;
        try {
            //验证直播信息
            Result<LiveRoom> result = liveRoomService.getLiveRoomById(dto.getRoomId());
            if(!result.isOk()){
                return Result.build(null,result.getCode(),result.getMessage());
            }
            LiveRoom liveRoom = result.getData();
            if(userId.equals(liveRoom.getUserId())){
                return Result.build(null,ResultCodeEnum.ANCHOR_CANNOT_GIVE_GIFT);
            }
            //验证礼物信息
            LiveGift gift = liveGiftService.getGiftById(dto.getGiveId());
            if(gift == null){
                return Result.build(null,ResultCodeEnum.GIVE_GIFT_NOT_EXIST);
            }
            //金额
            BigDecimal multiply = gift.getGiftPrice().multiply(new BigDecimal(dto.getCount().toString()));
            if(multiply.compareTo(new BigDecimal("0")) <= 0){
                return Result.build(null,ResultCodeEnum.INCORRECT_PAYMENT_AMOUNT);
            }
            orderNo = "LG"+oConvertUtils.orderNo();
            giftDto = new GivingLiveGiftDto(userId, liveRoom.getUserId(), multiply,orderNo);
            //账户扣款
            Result<Map<String, UserBalance>> mapResult = userBalanceFeignClient.giveLiveGiftUpdateBalance(giftDto);
            if(!mapResult.isOk()){
                return Result.build(null,mapResult.getCode(),mapResult.getMessage());
            }
            Map<String, UserBalance> data = mapResult.getData();
            UserBalance giver = data.get("giver");
            UserBalance recipient = data.get("recipient");
            String groupMsg = imUtil.sendGroupMsg(liveRoom.getGroupId(), userId, JSONUtil.toJsonStr(gift));
            if(StrUtil.isEmpty(groupMsg)){
                log.error("用户:{},赠送直播间:{},主播:{},礼物:{},发送IM消息失败",userId,liveRoom.getId(),liveRoom.getUserId(),dto.getGiveId());
                //发送IM消息失败,退款
                Result<ResultCodeEnum> updateBalance = userBalanceFeignClient.refundLiveGiftUpdateBalance(giftDto);
                if(!updateBalance.isOk()){
                    log.error("用户:{},赠送直播间:{},主播:{},礼物:{},退款失败,原因:{}",userId,liveRoom.getId(),liveRoom.getUserId(),dto.getGiveId(),updateBalance.getMessage());
                }
                return Result.build(null,ResultCodeEnum.GIVE_GIFT_FAIL);
            }
            LiveGiveGift giveGift = new LiveGiveGift();
            giveGift.setUserId(userId);
            giveGift.setGiveUserId(liveRoom.getUserId());
            giveGift.setGiftId(dto.getGiveId());
            giveGift.setRoomId(dto.getRoomId());
            giveGift.setGiveCount(dto.getCount());
            giveGift.setPrice(multiply);
            giveGift.setUserBalanceId(giver.getId());
            giveGift.setGiveUserBalanceId(recipient.getId());
            giveGift.setGiveTime(new Date());
            baseMapper.insert(giveGift);
        }catch (Exception e){
            if(!StrUtil.isEmpty(orderNo)){
                Result<ResultCodeEnum> updateBalance = userBalanceFeignClient.refundLiveGiftUpdateBalance(giftDto);
                if(!updateBalance.isOk()){
                    log.error("退款失败,原因:{},参数:{}",updateBalance.getMessage(),JSONUtil.toJsonStr(dto));
                }
            }
            log.error("用户赠送礼物失败,参数:{},异常:{}",JSONUtil.toJsonStr(dto),e.toString());
            return Result.build(null,ResultCodeEnum.GIVE_GIFT_FAIL);
        } finally {
            lock.unlock();
        }
        return Result.ok();
    }

    @Override
    public BigDecimal getUserConsumePrice(Long liveUserId, Long liveRoomId) {
        if(liveRoomId == null || liveRoomId == 0){
            return new BigDecimal("0");
        }
        return baseMapper.getUserConsumePrice(liveUserId,liveRoomId);
    }
}




